package com.cip.email.picasa.api;

import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.find;
import static org.apache.commons.lang.StringUtils.substringAfterLast;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Logger;

import com.cip.email.picasa.PicasaExceptionRuntime;
import com.cip.email.picasa.email.Email;
import com.cip.email.picasa.email.ImageAttachment;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;
import com.google.common.base.Throwables;
import com.google.gdata.client.photos.PicasawebService;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.media.MediaByteArraySource;
import com.google.gdata.data.photos.AlbumEntry;
import com.google.gdata.data.photos.PhotoEntry;
import com.google.gdata.data.photos.UserFeed;
import com.google.gdata.util.ServiceException;

public class PicasaAPI {
	private static final Logger log = Logger.getLogger(PicasaAPI.class.getName());
	
	private final PicasawebService picasawebService;
	private final String ROOT_URL = "https://picasaweb.google.com/data/feed/api";
	
	public PicasaAPI(PicasawebService picasawebService) {
		this.picasawebService = picasawebService;
	}
	
	public List<AlbumEntry> getAlbums() {
		try {
			URL feedUrl = new URL(ROOT_URL + "/user/picasaweb.cip?kind=album");
			UserFeed myUserFeed = picasawebService.getFeed(feedUrl, UserFeed.class);
			return myUserFeed.getAlbumEntries();
		} catch (IOException e) {
			throw new PicasaExceptionRuntime(e);
		} catch (ServiceException e) {
			throw new PicasaExceptionRuntime(e);
		}
	}
	
	public boolean hasAlbumByName(String name) {
		List<AlbumEntry> albums = getAlbums();
		return any( albums, PicasaFunctions.byName(name) );
	}
	
	public AlbumEntry getAlbumByName(final String name) {
		List<AlbumEntry> albums = getAlbums();
		return find(albums, PicasaFunctions.byName(name));
	}

	public void createAlbum(String newAlbum) {
		if (hasAlbumByName(newAlbum)) {
			return;
		}
		
		AlbumEntry myAlbum = new AlbumEntry();

		myAlbum.setTitle(new PlainTextConstruct(newAlbum));
		myAlbum.setDescription(new PlainTextConstruct("Created by the picasa-email application."));

		URL postUrl;
		try {
			postUrl = getURL(ROOT_URL + "/user/picasaweb.cip?kind=album");
			picasawebService.insert(postUrl, myAlbum);
		} catch (IOException e) {
			throw new PicasaExceptionRuntime(e);
		} catch (ServiceException e) {
			throw new PicasaExceptionRuntime(e);
		}
	}

	public void deleteAlbum(String newAlbum) {
		try {
			find(getAlbums(), PicasaFunctions.byName(newAlbum)).delete();
		} catch (IOException e) {
			throw new PicasaExceptionRuntime(e);
		} catch (ServiceException e) {
			throw new PicasaExceptionRuntime(e);
		}
		
	}
	
	public void uploadImage(Email email) {
		if (!any(getAlbums(), PicasaFunctions.byName(email.getSubject()))) {
			createAlbum(email.getSubject());
		}
		String albumId = find(getAlbums(), PicasaFunctions.byName(email.getSubject())).getId();	
		URL albumPostUrl = getURL(ROOT_URL + "/user/picasaweb.cip/albumid/" + substringAfterLast(albumId, "/"));

		List<ImageAttachment> attachments = email.getAttachments();
		for (ImageAttachment imageAttachment : attachments) {
			PhotoEntry myPhoto = new PhotoEntry();
			myPhoto.setTitle(new PlainTextConstruct(email.getSubject()));
			myPhoto.setDescription(new PlainTextConstruct(email.getBody()));
			
			byte[] content = imageAttachment.getContent();
			try{
				log.info("File size: " + content.length);
				content = resizeImage(content);
				log.info("After resize: " + content.length);
			}catch(Exception e) {
				//nothing to do;
			}
			MediaByteArraySource myMedia = new MediaByteArraySource(content,"image/jpeg");
			myPhoto.setMediaSource(myMedia);
			
			try {
				log.info("Before inserting the album");
				picasawebService.insert(albumPostUrl, myPhoto);
			} catch (IOException e) {
				Throwables.propagate(e);
			} catch (ServiceException e) {
				Throwables.propagate(e);
			}
		}
	}

	public byte[] resizeImage(byte[] imageData) {
		int width = 1280;
		int height = 960;

		int sizeLimit = 900000; //1048576 is the limit, but just making sure
		
		while (imageData.length > sizeLimit) { 
			Image oldImage = ImagesServiceFactory.makeImage(imageData);
			Transform resize = ImagesServiceFactory.makeResize(width, height);
			
			ImagesService imagesService = ImagesServiceFactory.getImagesService();
			Image newImage = imagesService.applyTransform(resize, oldImage);
			imageData = newImage.getImageData();
			if (imageData.length > sizeLimit) {
				width *= 0.90;
				height *= 0.90;
			}
		}
		
		return imageData;
	}
	
	private URL getURL(String url) {
		try {
			return new URL(url);
		} catch (MalformedURLException e) {
			throw new PicasaExceptionRuntime(e);
		}
	}
}

